/*
 * Created on Jul 5, 2005
 *
 */
package com.erclab.internal.xpresso.util;

import java.util.ArrayList;

import com.erclab.internal.xpresso.dataAccess.GenericResultSet;
import com.erclab.internal.xpresso.dataAccess.MysqlDatasource;
import com.erclab.internal.xpresso.dataAccess.Query;
import com.erclab.internal.xpresso.exceptions.ClonerException;
import com.erclab.internal.xpresso.exceptions.DataSourceException;
import com.erclab.internal.xpresso.forms.Form;
import com.erclab.internal.xpresso.reports.Report;
import com.erclab.internal.xpresso.conf.Settings;

/**
 * @author Enrique Rodriguez.
 *
 */
public class MysqlCloner implements Cloner {

	protected void cloneObject(String objectToClone, String newName, String ObjectType, int dataSourceId) throws ClonerException{
		
		String prefix = ObjectType.equalsIgnoreCase("Report")? "report" : "form";
		String attributesQuery = "SELECT * FROM App_" + prefix + "s WHERE " + prefix + "Name='" + objectToClone + "'";

		MysqlDatasource ads = (MysqlDatasource)Settings.getRepository().getApplicationDataSource(dataSourceId);
		GenericResultSet columns = null;
		GenericResultSet attributes = null;

		try {
			columns = ads.runQuery("DESCRIBE App_" + prefix + "s");
			attributes = ads.runQuery(attributesQuery);
		} catch (DataSourceException e) {
			throw new ClonerException("An error ocurred clonning: " + e);
		}
		
		if(!attributes.nextRow())
			throw new ClonerException("The object " + objectToClone + " does not exist.");
		
		// Create and execute insert query
		Query q = createNewObjectQuery(prefix, newName, columns, attributes);
		try {
			ads.executeQuery(q);
		} catch (DataSourceException e1) {
			throw new ClonerException("An error ocurred clonning: " + e1);
		}
		
		// Obtain new Object ID
		String newObjectId = getNewObjectId(ads, prefix, newName);
		createObjectElements(ads, prefix, objectToClone, newObjectId);
		
	}

	private void createObjectElements(MysqlDatasource ads, String prefix, String objectToClone, String newObjectId) throws ClonerException {

		String sqlObjectElements = "SELECT App_" + prefix + "Elements.* FROM App_" + prefix + "Elements, App_" + 
									prefix + "s WHERE App_" + prefix + "Elements.Id" + prefix + "="
									+ "App_" + prefix + "s.Id" + prefix + " AND " + 
									prefix + "Name='" + objectToClone + "'";
		
		GenericResultSet elements = null;
		GenericResultSet columns = null;
		try {
			elements = ads.runQuery(sqlObjectElements);
			columns = ads.runQuery("DESCRIBE App_" + prefix + "Elements");
		} catch (DataSourceException e) {
			throw new ClonerException("An error ocurred clonning: " + e);
		}
		
		ArrayList columnNames = new ArrayList();
		while(columns.nextRow()){
			columnNames.add(columns.getValue("Field"));
		}
		
		while(elements.nextRow()){
			StringBuffer sqlCloneElement = new StringBuffer("INSERT INTO App_" + prefix + "Elements (id" + prefix + ", ");
			StringBuffer sqlCloneElementSnd = new StringBuffer(" ) values(" +  newObjectId + ", ");
			
			ArrayList columnValues = new ArrayList();
			for (int i = 0; i < columnNames.size(); i++){
				String columnValue = elements.getRow()[i];
				if (!((String)columnNames.get(i)).equalsIgnoreCase("id" + prefix + "Element") && ! ((String)columnNames.get(i)).equalsIgnoreCase("id" + prefix)){
						sqlCloneElement.append(columnNames.get(i) + ", ");
						sqlCloneElementSnd.append("?, ");
						columnValues.add(columnValue);
				}
			}
			Query q = new Query();
			q.setQuery(sqlCloneElement.substring(0, sqlCloneElement.length()-2) + sqlCloneElementSnd.substring(0, sqlCloneElementSnd.length()-2) + ")");
			q.setValues((String[])columnValues.toArray(new String[columnValues.size()]));
			try {
				ads.executeQuery(q);
			} catch (DataSourceException e1) {
				throw new ClonerException("An error ocurred clonning: " + e1);
			}
			
		}
	}

	private String getNewObjectId(MysqlDatasource ads, String prefix, String newName) throws ClonerException {
		
		GenericResultSet grs = null;
		try {
			grs = ads.runQuery("SELECT Id" + prefix + " FROM App_" + prefix + "s WHERE " 
						+ prefix + "Name='" + newName + "'");
		} catch (DataSourceException e) {
			throw new ClonerException("An error ocurred clonning: " + e);
		}

		grs.nextRow();
		return grs.getRow()[0];
	}


	protected Query createNewObjectQuery(String prefix,	String newName, GenericResultSet columns, GenericResultSet attributes) {
		
		ArrayList values = new ArrayList();
		StringBuffer objectCloneQuery  = new StringBuffer("INSERT INTO App_" + prefix + "s (" + prefix + "Name, ");
		StringBuffer objectCloneQueryValues = new StringBuffer(" ) values(?, ");    
		values.add(newName);
				
		int count = 0;
		while(columns.nextRow()){
			String columnName = columns.getValue("Field");
			String columnValue = attributes.getValue(columnName);
			if(isValidColumnToClone(columnValue, columnName, prefix)){
				objectCloneQuery.append(columnName + ", ");
				objectCloneQueryValues.append("?, ");
				values.add(columnValue);
			}
		}
		
		Query q = new Query();
		q.setQuery(objectCloneQuery.substring(0, objectCloneQuery.length()-2) + objectCloneQueryValues.substring(0, objectCloneQueryValues.length()-2) + ")");
		q.setValues((String[])values.toArray(new String[values.size()]));
		return q;
		
	}
	
	
	/**
	 * @param columnValue
	 * @return
	 */
	private boolean isValidColumnToClone(String columnValue,String columnName, String prefix) {
		return columnValue != null && ! columnName.equalsIgnoreCase("id" + prefix) && ! columnName.equalsIgnoreCase(prefix + "Name");
	}


	public void cloneReport(Report theReport, String newReportName, int dataSourceId)
		throws ClonerException {
		cloneObject(theReport.getReportName(), newReportName, "Report", dataSourceId);

	}

	public void cloneForm(Form theForm, String newFormName, int dataSourceId)
		throws ClonerException {
			cloneObject(theForm.getFormName(), newFormName, "Form", dataSourceId);

	}

}
